#!/usr/bin/env python
import sys
import pygtk, gtk
import gtksourceview2
import gobject
import cairo, pango
from HollyWidgets.TreeViewBased import ICustomCellView, CellRendererCustom
from HollyWidgets.TreeViewBased.TreeView import HTreeNode, NodeCollection
from HollyWidgets.TreeViewBased.TreeView.Events import NodeEventArgs

class HTreeView( gtk.TreeView, ICustomCellView.IBaseListWidget ):

	def __init__( self ):
		gtk.TreeView.__init__(self)
		self.ownerDraw         = False
		self.ItemHeight        = 20
		#checkbox, text, HTreeNode, expanded icon, unexpanded icon
		self.store             = gtk.TreeStore( object )
		self.BaseColumn        = None
		#cells
		self.cell_chk          = gtk.CellRendererToggle()
		self.cell_icon         = gtk.CellRendererPixbuf()
		self.cell_text         = CellRendererCustom.CellRendererCustom( self )
		#node list
		self.Nodes             = NodeCollection.NodeCollection()
		#my events
		self.Events            = { 
			"NodeExpanded"       : None, "NodeCollapsed"    : None,
			"BeforeNodeCollapse" : None, "BeforeNodeExpand" : None,
			"NodeEdited"         : None, "DrawItem"         : None,
			"MeasureItem"        : None, "NodeRightClick"   : None }
                self.set_model( self.store )
                #default settings
                self.set_headers_visible( False )
                self.set_enable_search  ( True  )
                #
                self.AddBaseColumn()
                self.connect_after("row-expanded"     , self.OnExpandRow       )
                self.connect_after("row-collapsed"    , self.OnCollapseRow     )
                self.connect_after("test-expand-row"  , self.OnTestExpandRow   )
                self.connect_after("test-collapse-row", self.OnTestCollapseRow )
                #add cell edited change listener
                self.cell_text.connect_after("edited", self.OnTextEdited )
                #key listener
                self.connect("key-release-event", self.OnKeyReleased     )
	
       
	def connect_my_event( self, event_name, function ):
		if self.Events.index( event_name ) != -1:
			self.Events[ event_name ] = function
		else:
			print "event '" + event_name + "' does not exist"
			
	def AddBaseColumn( self ):
                self.BaseColumn             = gtk.TreeViewColumn()
                #set renderers properties
                self.cell_chk.connect("toggled", self.OnCellToggled )
                self.cell_chk.set_property ( "visible" , False )
                self.cell_text.set_property( "editable", True  )
                self.cell_icon.set_property( "visible", False )
                #
                self.BaseColumn.pack_start    ( self.cell_chk , False       )
                self.BaseColumn.pack_start    ( self.cell_icon, False       )
                self.BaseColumn.pack_start    ( self.cell_text, True        )
                #set datafuncs
                self.BaseColumn.set_cell_data_func( self.cell_chk , self.OnChkDataFunc  )
                self.BaseColumn.set_cell_data_func( self.cell_text, self.OnTextDataFunc )
                self.BaseColumn.set_cell_data_func( self.cell_icon, self.OnIconDataFunc )
                #add column
                self.append_column( self.BaseColumn )
                self.Nodes.connect("NodeAdded"  , self.OnNodeAdded   )
                self.Nodes.connect("NodeRemoved", self.OnNodeRemoved )
                self.Nodes.connect("NodeUpdated", self.OnNodeUpdated )
       
        def button_press_event ( self, evnt ):
		if evnt.button == 3 :
                        #get path at current mouse position
                        path = self.get_path_at_pos( int(evnt.X), int(evnt.Y) )
                        #get iter from path
                        iter = self.store.GetIter( path )
                        if self.Events["NodeRightClick"] != None:
                                #get node from iter
                                node   = self.getNodeFromIter( iter )
                                #raise event
                                self.Events["NodeRightClick"]( self, NodeEventArgs.NodeEventArgs( node ) )
                #TODO: vezi ce-i cu asta:
                return super.button-press-event( evnt )
               
	def OnTextEdited( self, sender, path, new_text ):
		iter = self.store.get_iter(  path )
		node = self.getNodeFromIter( iter )
		node.Text = new_text;
		if self.Events["NodeEdited"] != None:
			 self.Events["NodeEdited"]( self, NodeEventArgs.NodeEventArgs( node ) )
               
	def OnKeyReleased( self, sender, args ):
		#if selected node has children nodes, expanded or collapsed
		#on right/left arrow button press
		node = self.SelectedNode
		if node != None and node.Nodes.Count() > 0:
			if( args.Event.Key == gtk.gdk.Key.Right ):
				self.expandNode  ( node )
			elif args.Event.Key == gtk.gdk.Key.Left:
				self.collapseNode( node )
               
        #checkbox cell function
        def OnChkDataFunc(self, column, cell, model, iter ):
		nod = self.getNodeFromIter( iter )
		cell.set_property( "active", nod.get_checked() )

       
        #text cell function
        def OnTextDataFunc( self, column, cell, model, iter ):
		#renderer node text
                nod      = self.getNodeFromIter( iter )
                cell.set_property("text", nod.get_text() )
                #TODO:cell.set_property("iter", iter    )
       
        #icon data function
	def OnIconDataFunc( self, column, cell, model, iter):
		#get the treenode linked to the iter;
                nod        = self.getNodeFromIter( iter )
                #if cell is expanded show opened icon, else show closed icon
                if nod.get_opened_icon() != None:
                	if cell.get_property("is-expanded"):
        	                cell.set_property("pixbuf", nod.get_opened_icon() )
	                else:
        	                cell.set_property("pixbuf", nod.get_icon() )
       
        #checkbox state changed
	def OnCellToggled( self, sender, args ):
	    iter = store.GetIterFromString(args.Path)
	    if iter != None:
		nod         = self.getNodeFromIter( iter )
		nod.Checked = not( nod.Checked )
		#(de)select all childs
		if nod.Checked:
			nod.selectAllChilds()
		else:
			nod.deselectAllChilds()
       
        #returns a HTreeNode from an iter
	def getNodeFromIter( self, iter ):
                ret = None
                try:
			ret = self.store.get_value( iter, 0 )
                except:
                        ret = None
                return ret
               
               
#region node-events
	def OnNodeAdded( self, sender, args ):
		iter                = self.store.append( None, [ args.Node ] )
		args.Node.Store     = self.store
		args.Node.InnerIter = iter
		args.Node.Treeview  = self
		self.queue_draw()

	def OnNodeRemoved( self, sender, args ):
		iter = args.Node.InnerIter
		self.store.remove( iter )
		self.queue_draw()

	def OnNodeUpdated( self, sender, args ):
		args.NewNode.Store     = args.OldNode.Store;
		args.NewNode.InnerIter = args.OldNode.InnerIter;
		args.NewNode.Treeview  = args.OldNode.Treeview;
		self.store.SetValue( args.OldNode.InnerIter, 0 , args.NewNode );
		self.queue_draw()

	def OnExpandRow( self, sender, iter, path ):
		nod            = self.getNodeFromIter( iter )
		nod.IsExpanded = True
		if self.Events["NodeExpanded"] != None:
			self.Events["NodeExpanded"]( self, NodeEventArgs.NodeEventArgs( nod ) )
		self.queue_draw()

	def OnCollapseRow( self, sender, iter, path ):
		nod  = self.getNodeFromIter( iter )
		nod.IsExpanded = False
		if self.Events["NodeCollapsed"] != None:  
			self.Events["NodeCollapsed"]( self, NodeEventArgs.NodeEventArgs( nod ) )
		self.queue_draw()

	def OnTestExpandRow( self, sender, iter, path ):
		node = self.getNodeFromIter( iter )
		if self.Events["BeforeNodeExpand"] != None:
			self.Events["BeforeNodeExpand"]( self, NodeEventArgs.NodeEventArgs( node ) )

	def OnTestCollapseRow( self, sender, iter, path ):
		node = self.getNodeFromIter( iter )
		if self.Events["BeforeNodeCollapse"] != None:
			self.Events["BeforeNodeCollapse"]( self, NodeEventArgs.NodeEventArgs( node ) )
#endregion
	def selectNode( self, node ):
		path = self.get_model().get_path( node.InnerIter )
		self.get_selection().select_path( path )
		#move cursor to selection
		self.set_cursor( path, self.get_column(0), False )

	def expandNode( self, node ):
		path = self.get_model().get_path( node.InnerIter )
		self.expand_to_path( path )

	def collapseNode( self, node ):
		path = self.get_model().get_path( node.InnerIter )
		self.collapse_row( path )

	def OnMeasureItem ( ItemIndex, iter, widget, cell_area, result ):      
		args = MeasureItemEventArgs( ItemIndex, iter, cell_area )
		#
		if self.OwnerDraw and self.Events["MeasureItem"] != None:
			self.Events["MeasureItem"]( self, args )
		else:
			args.ItemHeight  = ItemHeight
			result.X       = args.ItemLeft
			result.Y       = args.ItemTop
			result.Width   = args.ItemWidth
			result.Height  = args.ItemHeight

	def OnDrawItem ( ItemIndex, iter, window,  widget,  background_area, cell_area, expose_area, flags):
		args = DrawItemEventArgs( ItemIndex, iter, window, widget, background_area, cell_area, expose_area, flags );
		#
		if self.OwnerDraw and self.Events["DrawItem"] != None:
			self.Events["DrawItem"]( self, args )
		else:  
			text  = self.getNodeFromIter( args.Iter ).Text
			l     = Pango.Layout( self.pango_context );
			l.set_text( text )
			width, height = l.GetPixelSize()
			args.Drawable.draw_layout( self.get_style().text_gc( self.State ) , args.CellArea.X, args.CellArea.Y + (height/2), l )

               
#region properties
	@property
	def OwnerDraw(self):
		return self.ownerDraw

	def OwnerDraw(self, value):
		self.ownerDraw = value
		self.queue_draw()

	@property     
	def NodeIconVisible(self):
		return self.cell_icon.get_visible()


	def NodeIconVisible(self,value):
		self.cell_icon.set_property( "visible", value )
		self.get_column(0).queue_resize()
		self.queue_draw()

	@property      
	def IsCheckBoxTree(self):
		return self.cell_chk.get_visible()


	def IsCheckBoxTree(self,value):
		self.cell_chk.set_visible( value )
		self.get_column(0).queue_resize()
		self.queue_draw()

	@property
	def IsDragAndDropEnable(self):
		return self.get_reorderable()


	def IsDragAndDropEnable(self,value):
		self.set_reorderable( value )

	@property
	def Editable(self):
		return self.cell_text.get_editable()

	def Editable(self,value):
		self.cell_text.set_editable( value )
		self.get_column(0).queue_resize()
		self.queue_draw()

	@property
	def SelectedNodes(self):
		model, paths = self.get_selection().get_selected_rows()
		ret          = []
		for i in range(0, len( paths ) ):
			path = paths[i]
			iter = self.store.get_iter( path )
			ret.append( self.getNodeFromIter(iter) )
		return ret

	@property
	def SelectedNode(self):
		if len( self.SelectedNodes ) > 0:
			return self.SelectedNodes[0]
		else:
			return None

